#ifndef MODBUS_H
#define MODBUS_H

#include "global.h"
#include "config.h"

extern unsigned char server_address; //设备地址

//------------------------------------------
// RO-BIT
//------------------------------------------
typedef struct RO_BIT{
    bit x_at_home:1;       // x在原点
    bit y_at_home:1;       // Y在原点
    bit z_at_home:1;       // z在原点
    bit pick_cup_sensor:1; // 抓手已下降到抓杯/放杯位置。1：到位；0：不到位。
    bit holding_cup:1;     // 抓手中有无测试杯状态 1：有； 0：无
    bit y_at_limit:1;      // Y限位状态 1：在限位位置；0：不在限位位置
}RO_BIT;
extern  RO_BIT ro_bit;
#define RO_BIT_FIRST        ((uchar*)&ro_bit)
#define RO_BIT_COUNT        6
//------------------------------------------
// RW-BIT
//------------------------------------------
__packed typedef struct RW_BIT{
    bit elector_manget:1; // 设置抓手电磁铁状态。写入 1 使能电磁铁，打开抓手；写入 0 关闭电磁铁，关闭抓手
}RW_BIT;
extern  RW_BIT rw_bit;
#define RW_BIT_FIRST        ((uchar*)&rw_bit)
#define RW_BIT_COUNT        1

//==========================================================
// RW-WORD
//==========================================================
__packed typedef struct RW_WORD
{
    ushort x_max_speed;              // X最大速度, 0.01 rad/sec^2
    long x_max_distance;             // X最大行程
    ushort y_max_speed;              // Y最大速度, 0.01 rad/sec^2
    long y_max_distance;             // Y最大行程
    ushort z_max_speed;              // z最大速度，0.01 rad/sec^2
    long z_max_distance;             // z最大行程
    ushort m_max_speed;              // 混匀电机最高速度。
    ushort action;                   // 动作指令
    long x_target;                   // X目标位置
    long y_target;                   // y目标位置
    long z_target;                   // z目标位置
    long flags;                      // 动作标识
    long x_target_2;                 // X目标坐标2
    long y_target_2;                 // y目标坐标2
    long z_target_2;                 // z目标坐标2
    RECT range;                      // 运行范围
    RECT block[MAX_BLOCK_COUNT];     // 禁止运行范围
}RW_WORD;
extern RW_WORD rw_word;
#define RW_WORD_FIRST       (&rw_word.x_max_speed)
#define RW_WORD_COUNT       0x2A

typedef enum RW_LONG_ADD
{
    X_MAX_DISTANCE_L = 0x01,
    X_MAX_DISTANCE_H ,
    Y_MAX_DISTANCE_L = 0x04,
    Y_MAX_DISTANCE_H,
    Z_MAX_DISTANCE_L = 0x07,
    Z_MAX_DISTANCE_H,
    X_TARGET_L = 0x0B,
    X_TARGET_H,
    Y_TARGET_L = 0x0D,
    Y_TARGET_H,
    Z_TARGET_L = 0x0F,
    Z_TARGET_H,
    FLAGS_L = 0x11,
    FLAGS_H,
    X_TARGET_2_L = 0x13,
    X_TARGET_2_H,
    Y_TARGET_2_L = 0x15,
    Y_TARGET_2_H,
    Z_TARGET_2_L = 0x17,
    Z_TARGET_2_H,

    RW_LONG_COUNT = 10,
}RW_LONG_ADD;

extern RW_LONG_ADD rw_long_addL[RW_LONG_COUNT];
extern RW_LONG_ADD rw_long_addH[RW_LONG_COUNT];

//==========================================================
// RO-WORD
//==========================================================
__packed typedef struct RO_WORD{
    long x_pos;              // x当前坐标, step
    long y_pos;              // Y当前坐标，step
    long z_pos;              // z当前坐标，step
    ushort x_duration;       // x运动经过的时间, ms
    long x_distance;         // x经过的位移
    ushort y_duration;       // Y运动经过的时间
    long y_distance;         // Y经过的位移
    ushort z_duration;       // Z运动经过的时间
    long z_distance;         // Z经过的位移
    long z_pick_cup_pos;     // z检测到的抓杯/放杯位置
    long m_pos;              // M当前坐标, step
    ushort m_duration;         // M运动经过的时间, ms
    long m_distance;         // M经过的位移
}RO_WORD;
extern RO_WORD ro_word;
#define RO_WORD_FIRST       ((ushort*)&ro_word.x_pos)
#define RO_WORD_COUNT       22

//------------------------------------------
// 事件
//------------------------------------------
#define MAX_EVENT_COUNT                                64                // 2^n
#define MAX_EVENT_MASK                                (MAX_EVENT_COUNT-1)

// 接收事件
#define EVENT_RECEIVED                                0x80        // 接收事件
#define EVENT_BROADCAST                               0x40        // 接收到广播消息
#define EVENT_LISTEN_ONLY                             0x20        // 当前处于只听模式
#define EVENT_CHARRACTER_OVERRUN                      0x10        // 字符过载
#define EVENT_COMMUNICATION_ERROR                     0x02        // 通讯错误

// 发送事件
#define EVENT_SENT                                    0x40        // 发送事件
//#define EVENT_LISTEN_ONLY                           0x20        // 当前处于只听模式
#define EVENT_WRITE_TIMEOUT                           0x10        // 写超时
#define EVENT_EXCEPTION                               0x80        // 异常应答
#define EVENT_BUSY_EXCEPTION                          0x04        // 错误代码 5-6
#define EVENT_ABORT_EXCEPTION                         0x02        // 错误代码 4
#define EVENT_READ_EXCEPTION                          0x01        // 错误代码 1-3

// 进入只听模式事件
#define EVENT_ENTER_LISTEN_ONLY     0x04    // 进入只听模式事件

//------------------------------------------
// 异常应答代码
//------------------------------------------
#define ILLEGAL_FUNCTION            0x01
#define ILLEGAL_DATA_ADDRESS        0x02
#define ILLEGAL_DATA_VALUE          0x03
#define SERVER_DEVICE_FAILURE       0x04
#define ACKNOWLEDGE                 0x05
#define SERVER_DEVICE_BUSY          0x06
#define MEMORY_PARITY_ERROR         0x08
#define GATEWAY_PATH_UNAVAILABLE    0x0A
#define GATEWAY_TARGET_NO_RESPONSE  0x0B

//------------------------------------------
// 文件
//------------------------------------------
#define FILE_COUNT              1
#define MAX_FILE_REQUEST        2       // 一次请求最大的子记录访问数量

#define FILE_BUFFER_SIZE        256
#define FILE_BUFFER_MASK        (FILE_BUFFER_SIZE-1)

extern ushort  file_buf[FILE_BUFFER_SIZE];
//------------------------------------------
// 诊断
//------------------------------------------
extern ushort  diagnostic;
extern ushort  bus_message_count;      // 总线上消息数量
extern ushort  bus_error_count;        // 总线上通讯错误数量
extern ushort  bus_exception_count;      // 总线上异常应答数量
extern ushort  server_message_count;        // 下位机消息数量
extern ushort  server_no_response_count;        // 下位机未响应消息数量
extern ushort  server_exception_count;        // 下位机异常应答消息数量
extern ushort  server_status;
extern uchar   program_status;
extern ushort  server_busy_count;
extern ushort  bus_char_overrun_count;

extern bit ps_listen_only;                    // 处于只听模式
extern bit ps_server_busy;                  // 设备忙

extern uchar event_count;                                        // 事件记数值, event_count索引的event_log为当前事件
extern uchar event_log[MAX_EVENT_COUNT];        // 事件记录

ushort from_little_endian_16(ushort n);//将多字节数转换为小端模式
ulong from_little_endian_32(ulong n);

void register_init(void);

void Read_Address(void);//获取id
void Device_Init(void);//初始化id

void No_Response(void);
void Exception_Response(uchar err);
void Response(void);

uchar Read_RW_bit(ushort addr, uchar n);
uchar Read_RO_bit(ushort addr, uchar n);
void write_bits(uchar *bits, ushort addr, uchar val, uchar n);
void Write_bit(ushort addr, uchar val, uchar n);
void Write_RO_bit(ushort addr, uchar val, uchar n);
ushort Read_RW_word(ushort addr);
ushort Read_RO_word(ushort addr);
void Write_word(ushort addr, ushort val);

void Log_Event(uchar event);//事件记录
void Process_Request(void);//处理上位机请求

// 读取异常状态
uchar Read_Exception(void);
// 诊断
void Diagnose(void);

void Read_Identification(void);

void Process_Main_Loop(void);
void Main_Loop(void);

#if FILE_COUNT
// 文件操作
void Reset_File(uchar fid);
void Append_File(uchar fid, ushort *rec, ushort n);
ushort Read_File(uchar fid, ushort addr);
void Write_File(uchar fid, ushort addr, ushort val);
ushort File_Size(uchar fid);
#endif//FILE_COUNT

#endif
